package com.changgou.oauth.service.impl;

import com.changgou.common.exception.ExceptionCast;
import com.changgou.common.model.response.user.UserCode;
import com.changgou.oauth.service.AuthService;
import com.changgou.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value( "${auth.ttl}" )
    private Long ttl;



    @Override
    public AuthToken login(String username, String password, String clientId, String clientSecret) {
        //构建请求地址
        ServiceInstance serviceInstance = loadBalancerClient.choose( "user-auth" );
        URI uri = serviceInstance.getUri();
        String url = uri+"/oauth/token";

        MultiValueMap<String,String> body = new LinkedMultiValueMap<>( );
        body.add( "grant_type","password" );
        body.add( "username",username );
        body.add( "password",password );

        MultiValueMap<String,String> headers = new LinkedMultiValueMap<>( );
        headers.add( "Authorization",this.getHttpBasic(clientId,clientSecret) );

        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>( body, headers );

        //对400 401 异常不处理，直接返回给前端
        restTemplate.setErrorHandler( new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if (response.getRawStatusCode() !=400 && response.getRawStatusCode() != 401){
                    super.handleError( response );
                }
            }
        } );

        //发送请求
        ResponseEntity<Map> responseEntity = restTemplate.exchange( url, HttpMethod.POST, requestEntity, Map.class );
        Map map = responseEntity.getBody();
        if (map == null || map.get( "access_token" )==null || map.get( "refresh_token" )==null || map.get( "jti" )==null ){
            ExceptionCast.cast( UserCode.USER_AUTH_LOGIN_ERROR );
        }
        //封装结果数据
        AuthToken authToken = new AuthToken();
        authToken.setAccessToken( (String) map.get( "access_token" ) );
        authToken.setRefreshToken( (String) map.get( "refresh_token" ) );
        authToken.setJti( (String) map.get( "jti" ) );

        //将jti作为redis中的key，jwt作为redis中的value进行数据的存放
        stringRedisTemplate.boundValueOps( authToken.getJti() ).set( authToken.getAccessToken(),ttl, TimeUnit.SECONDS );

        return authToken;
    }

    //生成请求头 Authorization: Basic Y2hhbmdnb3U6Y2hhbmdnb3U=
    private String getHttpBasic(String clientId, String clientSecret) {
        String value = clientId+":"+clientSecret;
        byte[] encode = Base64Utils.encode( value.getBytes() );
        return "Basic "+new String( encode );
    }
}
